// Polyline with arrows
//
// Bill Chadwick May 2008
//
// Free for any use
//

// Constructor params exactly as GPolyline then 
// 3) arrow spacing in pixels, 
// 4) arrow head length in pixels
// 5) arrow colour
// 6) arrow thickness in pixels
// 7) arrow opacity

function BDCCArrowedPolyline(pointsSentido, encodeJSON, gapPx, headLength, headColor, headWeight, headOpacity) {	
    
	this.encodeJSON = encodeJSON;
    this.gapPx = gapPx;
    this.headLength = headLength;
    this.headColor = headColor;
    this.headWeight = headWeight;
    this.headOpacity = headOpacity;
    this.heads = new Array();
    this.line = null;
	this.removed = false;
	this.pointsSentido = pointsSentido;
    
}
BDCCArrowedPolyline.prototype = new GOverlay();


BDCCArrowedPolyline.prototype.initialize = function(map) {

    this.map = map;   
    this.prj = map.getCurrentMapType().getProjection();
    var rdrw = GEvent.callback(this,this.recalc );
  	this.lstnMoveEnd = GEvent.addListener(map,"zoomend",function(){rdrw ();});
  	this.lstnType = GEvent.addListener(map,"maptypechanged",function(){rdrw ();});

  	this.recalc();//first draw
}

BDCCArrowedPolyline.prototype.remove = function() {

    try{
        if (this.line){
            this.map.removeOverlay(this.line);
			this.line=null;
		}
        for(var i=0; i<this.heads.length; i++)
            this.map.removeOverlay(this.heads[i]); 
    }
    catch(ex)
    {
    }
}

BDCCArrowedPolyline.prototype.clear = function() {
	this.remove();
	this.removed=true;
}

BDCCArrowedPolyline.prototype.redraw = function(force) {
	return;//do nothing, the GPolyline line and heads draw themselves
	
}


BDCCArrowedPolyline.prototype.copy = function(map) {
    return new BDCCArrowedPolyline(this.encodeJSON,this.gapPx, this.headLength, this.headColor, this.headWeight, this.headOpacity);
}


BDCCArrowedPolyline.prototype.recalc = function() {
   
   if (this.removed) return;

   var zoom = this.map.getZoom();
   this.remove();

  //the main polyline
   if (this.line == null){
	   this.line = new GPolyline.fromEncoded(this.encodeJSON);
   	   this.map.addOverlay(this.line);
   }

   // the arrow heads
   this.heads = new Array();

   var p1; // = this.prj.fromLatLngToPixel(this.pointsSentido[0],  zoom);//first point
   var p2;//next point
   var dx;
   var dy;
   var sl;//segment length
   var theta;//segment angle
   var ta;//distance along segment for placing arrows
   pxDistance = 0;
   pAnt = this.prj.fromLatLngToPixel(this.pointsSentido[0],  zoom);
   for (var i=0; i<this.pointsSentido.length; i=i+2){
      p1 = this.prj.fromLatLngToPixel(this.pointsSentido[i],  zoom);      
      p2 = this.prj.fromLatLngToPixel(this.pointsSentido[i+1],  zoom);
      dx = p2.x-p1.x;
      dy = p2.y-p1.y;
      sl = Math.sqrt((dx*dx)+(dy*dy)); 
      theta = Math.atan2(-dy,dx);
	  
	  pDX = pAnt.x - p2.x;
	  pDY = pAnt.y - p2.y;
      pxDistance += Math.sqrt((pDX*pDX)+(pDY*pDY));
	  pAnt = p2;
      //j=1;
      //just put one arrow in the middle of the line*/
	  if ((pxDistance>100)||(i==0)){
      	var x = p1.x + ((sl/2) * Math.cos(theta)); 
      	var y = p1.y - ((sl/2) * Math.sin(theta));
      	this.addHead(x,y,theta,zoom);
		pxDistance=0;
	  }
   }
}

BDCCArrowedPolyline.prototype.addHead = function(x,y,theta,zoom) {

    //add an arrow head at the specified point
    var t = theta + (Math.PI/4);
    if(t > Math.PI)
        t -= 2*Math.PI;
    var t2 = theta - (Math.PI/4);
    if(t2 <= (-Math.PI))
        t2 += 2*Math.PI;
    var pts = new Array();
	lenght = this.headLength;
    var x1 = x-Math.cos(t)*lenght;
    var y1 = y+Math.sin(t)*lenght;
    var x2 = x-Math.cos(t2)*lenght;
    var y2 = y+Math.sin(t2)*lenght;
    pts.push(this.prj.fromPixelToLatLng(new GPoint(x1,y1), zoom));
    pts.push(this.prj.fromPixelToLatLng(new GPoint(x,y), zoom));    
    pts.push(this.prj.fromPixelToLatLng(new GPoint(x2,y2), zoom));
    this.heads.push(new GPolyline(pts,this.headColor,this.headWeight,this.headOpacity,this.opts));
    this.map.addOverlay(this.heads[this.heads.length-1]);
}

